﻿using System;
using System.Collections.Generic;
using System.Text;

using System.Drawing;
using Microsoft.DirectX;

namespace NGE
{
    [Serializable]
    public enum ButtonboxState
    {
        Idle,
        Up,
        Down,
        Focus,
    }
    [Serializable]
    public delegate void MenuEvent(object sender, object arg);
    [Serializable]
    public class MenuElement
    {
        public Guid GUID;
        public string Name;
        public Vector3 Location;
        public Size Size;
        public Color FilterColor;
        public Color BGColor;
        public NImage BGImage;
        //public bool IsHide;
        public bool IsHide;
        //public bool IsHide
        //{
        //    get
        //    {
        //        return isHide;
        //    }
        //    set
        //    {
        //        isHide = value;
        //        if (value)
        //        {
        //            OnPanelboxShow(this, null);
        //        }
        //    }
        //}
        public Rectangle Zone
        {
            get
            {
                return new Rectangle((int)Location.X, (int)Location.Y, Size.Width, Size.Height);
            }
        }

        public MenuElement()
        {
            GUID = Guid.NewGuid();
            Name = "";
            FilterColor = Color.FromArgb(255, Color.White);
            //Size = new Size();
            BGColor = Color.FromArgb(255, Color.Black);
            BGImage = null;
        }
    }

    [Serializable]
    public class Panelbox : MenuElement
    {
        public Panelbox(Game g)
            : base()
        {
            Location = new Vector3();
            Size = new System.Drawing.Size(320, 240);
            BGColor = Color.Black;
            game = g;
            Elements = new List<MenuElement>();
            Buttonboxes = new List<Buttonbox>();
            OnKeyboardEvent = new KeyboardEvent(OnKeyboardEventCode);
            OnPanelboxOpen = new MenuEvent(OnPanelboxOpenCode);
            OnPanelboxClose = new MenuEvent(OnPanelboxCloseCode);
            OnPanelboxRefresh = new MenuEvent(OnPanelboxRefreshCode);
            //OnPanelboxShow += new MenuEvent(OnPanelboxShowCode);
        }

        void OnPanelboxRefreshCode(object sender, object arg)
        {
        }

        void OnPanelboxCloseCode(object sender, object arg)
        {
        }

        void OnPanelboxShowCode(object sender, object arg)
        {
        }

        void OnPanelboxOpenCode(object sender, object arg)
        {
        }
        public void ResetButtonboxIndex()
        {
            focusedButtonboxIndex = -1;
            FocusNextButtonbox();
        }
        public virtual void Refresh(object sender, object arg)
        {
            OnPanelboxRefresh(sender, arg);
        }
        //public virtual void Open(object sender, object arg)
        //{
        //    Open(sender, Location, arg);
        //}
        public virtual void Open(object sender, Vector3 loc, object arg)
        {
            if (loc != null)
            {
                Location = loc;
            }            
            focusedButtonboxIndex = -1;
            FocusNextButtonbox();
            OnPanelboxOpen(sender, arg);
        }
        public void Close(object sender, object arg)
        {
            OnPanelboxClose(sender, arg);
            //game.ClosePanelbox();
        }

        public void AddElement(MenuElement me)
        {
            if (me is Buttonbox)
            {
                Buttonboxes.Add((Buttonbox)me);
            }
            else
            {
                Elements.Add(me);
            }
        }

        protected event MenuEvent OnPanelboxOpen;
        protected event MenuEvent OnPanelboxClose;
        protected event MenuEvent OnPanelboxRefresh;

        protected virtual void OnKeyboardEventCode(object sender, int key, KeyboardState ks)
        {
            {
                if (ks == KeyboardState.KeyDown || ks == KeyboardState.KeyHold)
                {
                    if (key == game.Option.KeyA)
                    {
                        if (focusedButtonboxIndex > -1)
                        {
                            Buttonboxes[focusedButtonboxIndex].Down(focusedButtonboxIndex);
                        }
                    }
                }
                else if (ks == KeyboardState.KeyUp)
                {
                    if (key == game.Option.KeyD)
                    {
                        FocusNextButtonbox();
                    }
                    else if (key == game.Option.KeyU)
                    {
                        FocusPreButtonbox();
                    }
                    else if (key == game.Option.KeyA)
                    {
                        if (focusedButtonboxIndex > -1)
                        {
                            Buttonboxes[focusedButtonboxIndex].Up(focusedButtonboxIndex);
                            Buttonboxes[focusedButtonboxIndex].Focus(focusedButtonboxIndex);
                        }
                    }
                    else if (key == game.Option.KeyB)
                    {
                        game.MenuCOM.Close();
                    }
                }
            }
        }
        protected event KeyboardEvent OnKeyboardEvent;
        protected event MouseEvent OnMouseEvent;
        protected event GamepadEvent OnGamepadEvent;
        public List<MenuElement> Elements = new List<MenuElement>();
        public List<Buttonbox> Buttonboxes = new List<Buttonbox>();
        protected int focusedButtonboxIndex;
        [NonSerialized]
        protected Game game;
        public void FocusNextButtonbox()
        {
            if (Buttonboxes.Count < 1)
            {
                return;
            }
            focusedButtonboxIndex++;
            if (focusedButtonboxIndex == Buttonboxes.Count)
            {
                focusedButtonboxIndex--;
            }
            for (int i = 0; i < Buttonboxes.Count; i++)
            {
                Buttonboxes[i].Idle(i);
            }
            Buttonboxes[focusedButtonboxIndex % Buttonboxes.Count].Focus(focusedButtonboxIndex % Buttonboxes.Count);
            //if (Buttonboxes[focusedButtonboxIndex % Buttonboxes.Count].IsHide)
            //{
            //    FocusNextButtonbox();
            //}
        }
        public void FocusPreButtonbox()
        {
            if (Buttonboxes.Count < 1)
            {
                return;
            }
            focusedButtonboxIndex--;
            if (focusedButtonboxIndex < 0)
            {
                focusedButtonboxIndex++;
            }
            for (int i = 0; i < Buttonboxes.Count; i++)
            {
                Buttonboxes[i].Idle(i);
            }
            Buttonboxes[focusedButtonboxIndex % Buttonboxes.Count].Focus(focusedButtonboxIndex % Buttonboxes.Count);
        }
        public void NotifyKeyboardEvent(int key, KeyboardState ks)
        {
            OnKeyboardEvent(null, key, ks);
        }
        public void NotifyMouseEvent(int x, int y, MouseState ms)
        {
            OnMouseEvent(null, x, y, ms);
        }
        public void NotifyGamepadEvent(int sender, int btn, GamepadState gs)
        {
            OnGamepadEvent(sender, btn, gs);
        }
    }

    [Serializable]
    public class Imagebox : MenuElement
    {
        public Imagebox()
            : base()
        { }
        public NImage Image;
    }

    [Serializable]
    public class Textbox : MenuElement
    {
        public Textbox()
            : base()
        {
            TextColor = Color.White;
            TextFontName = "Microsoft JhengHei";
            TextFontSize = 12;
            TextFontStyle = FontStyle.Regular;
        }
        [NonSerialized]
        Timer timer;
        string text;
        [NonSerialized]
        int charIndex;
        public string TextFontName;
        public float TextFontSize;
        public FontStyle TextFontStyle;
        public Color TextColor;
        public int Interval;

        public Font TextFont
        {
            get
            {
                return new System.Drawing.Font(TextFontName, TextFontSize, TextFontStyle, GraphicsUnit.Pixel);
            }
        }
        public string Text
        {
            set
            {
                text = value;
                Reset();
            }
            get
            {
                if (text == null)
                {
                    return "";
                }
                if (text.Length == 0)
                {
                    return "";
                } if (Interval == 0)
                {
                    return text;
                }
                else
                {

                    if (charIndex <= 0)
                    {
                        timer = new Timer();
                        charIndex++;
                    }
                    timer.Record();
                    if (timer.Seconds > Interval / 1000.0)
                    {
                        timer.Reset();
                        if (charIndex < text.Length)
                        {
                            charIndex++;
                        }
                    }
                    return text.Substring(0, charIndex);
                }
            }
        }
        public void Reset()
        {
            charIndex = 0;
        }

        public string[] Lines
        {
            get
            {
                return Text.Split(new string[] { "\n", "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
            }
        }
    }

    [Serializable]
    public class Buttonbox : MenuElement
    {
        public Buttonbox()
            : base()
        {
            Textbox = new Textbox();
            timer = new Timer();
            //lastUpdateTime = 0;
        }
        [NonSerialized]
        Timer timer;
        public Textbox Textbox;
        //double lastUpdateTime;
        
        public Color TextColor
        {
            get
            {
                //int r = 255;
                //int g = 255;
                //int b = 255;
                //if (timer.TotalSeconds - lastUpdateTime > 0.100)
                //{
                //    r = Util.Roll(0, 255);
                //    g = Util.Roll(0, 255);
                //    b = Util.Roll(0, 255);
                //    lastUpdateTime = timer.TotalSeconds;
                //}
                //if (State == ButtonboxState.Focus)
                //{
                //    return Color.Red;
                //}
                //else if (State == ButtonboxState.Down)
                //{
                //    return Textbox.TextColor;
                //}
                //else if (State == ButtonboxState.Up)
                //{
                //    return Textbox.TextColor;
                //}
                //else
                //{
                //    return Textbox.TextColor;
                //}
                return Textbox.TextColor;
            }
        }
        public Font TextFont
        {
            get
            {
                //float offset = (float)timer.TotalSeconds;
                //offset *= 10;
                //offset %= 1;
                //offset -= 0;
                //if (State == ButtonboxState.Focus)
                //{
                //}
                //else if (State == ButtonboxState.Down)
                //{
                //    offset = 0;
                //}
                //else if (State == ButtonboxState.Up)
                //{
                //    offset = 1;
                //}
                //else
                //{
                //    offset = 0;
                //}

                //return new Font(Textbox.TextFontName, Textbox.TextFontSize + offset, Textbox.TextFontStyle, GraphicsUnit.Pixel);
                return Textbox.TextFont;
            }
        }
        public string Text
        {
            get
            {
                string txt = Textbox.Text;
                if (State == ButtonboxState.Focus)
                {
                    txt = ">" + txt;
                }
                else if (State == ButtonboxState.Down)
                {
                    txt = " " + txt;
                }
                else if (State == ButtonboxState.Up)
                {
                    txt = " " + txt;
                }
                else
                {
                    txt = " " + txt;
                }
                return txt;
            }
        }

        public int StopIndex;
        public ButtonboxState State;
        public event MenuEvent OnButtonboxEvent;
        public void Idle(int index)
        {
            StopIndex = index;
            State = ButtonboxState.Idle;
            OnButtonboxEvent(this, State);
        }
        public void Up(int index)
        {
            StopIndex = index;
            State = ButtonboxState.Up;
            OnButtonboxEvent(this, State);
        }
        public void Down(int index)
        {
            StopIndex = index;
            State = ButtonboxState.Down;
            OnButtonboxEvent(this, State);
        }
        public void Focus(int index)
        {
            StopIndex = index;
            State = ButtonboxState.Focus;
            OnButtonboxEvent(this, State);
        }
    }
}
